package org.zjvis.datascience.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.zjvis.datascience.common.dto.ActionDTO;
import org.zjvis.datascience.common.dto.TaskDTO;
import org.zjvis.datascience.common.dto.TaskInstanceDTO;
import org.zjvis.datascience.common.widget.dto.WidgetDTO;
import org.zjvis.datascience.common.enums.ActionEnum;
import org.zjvis.datascience.common.enums.TaskTypeEnum;
import org.zjvis.datascience.common.exception.DataScienceException;
import org.zjvis.datascience.common.util.CollectionUtil;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.util.PipelineUtil;
import org.zjvis.datascience.common.vo.ActionVO;
import org.zjvis.datascience.service.dataprovider.GPDataProvider;
import org.zjvis.datascience.service.mapper.ActionMapper;
import org.zjvis.datascience.service.mapper.TaskInstanceMapper;
import org.zjvis.datascience.service.mapper.TaskMapper;
import org.zjvis.datascience.service.mapper.WidgetMapper;

import javax.annotation.PreDestroy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @description Action操作 Service
 * @date 2021-12-23
 */
@Service
public class ActionService {

    private final static Logger logger = LoggerFactory.getLogger("ActionService");

    @Autowired
    private ActionMapper actionMapper;

    @Autowired
    private ActionStackWrapper actionStackWrapper;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private TaskInstanceMapper taskInstanceMapper;

    @Autowired
    private WidgetMapper widgetMapper;

    @Lazy
    @Autowired
    private TaskService taskService;

    @Autowired
    @Lazy
    private TColumnService tColumnService;

    @Autowired
    private GPDataProvider gpDataProvider;

    public List<ActionDTO> queryLatestActionByProjectId(Long projectId, Long limitNum) {
        return actionMapper.queryLatestActionByProjectId(projectId, limitNum);
    }

    public List<ActionDTO> queryLatestActionByPipelineId(Long pipelineId, Long limitNum) {
        return actionMapper.queryLatestActionByPipelineId(pipelineId, limitNum);
    }

    public boolean save(ActionDTO actionDTO) {
        return actionMapper.save(actionDTO);
    }

    public void delete(Long id) {
        actionMapper.delete(id);
    }

    public ActionDTO queryById(Long id) {
        return actionMapper.queryById(id);
    }

    /**
     * 添加action
     * @param actionType 操作类型
     * @param ctx1 操作前现场
     * @param ctx2 操作后现场
     * @return
     */
    public boolean addActionForTask(ActionEnum actionType, List<TaskDTO> ctx1, List<TaskDTO> ctx2) {
        return this.addActionForTask(actionType, ctx1, ctx2, null);
    }

    public boolean addActionForTask(ActionEnum actionType, List<TaskDTO> ctx1, List<TaskDTO> ctx2, List<TaskDTO> ctx3) {
        return addActionForTask(actionType, ctx1, ctx2, ctx3, new JSONObject());
    }

    public boolean addActionForTask(ActionEnum actionType, List<TaskDTO> ctx1, List<TaskDTO> ctx2, List<TaskDTO> ctx3, JSONObject context) {
        if (ctx1 == null || ctx1.size() == 0) {
            return false;
        }
        TaskDTO task = ctx1.get(0);
        //this.initStackForProjectId(task.getProjectId());
        this.initStackForPipelineId(task.getPipelineId());
        ActionDTO actionDTO = new ActionDTO();
        actionDTO.setUserId(task.getUserId());
        actionDTO.setProjectId(task.getProjectId());
        actionDTO.setPipelineId(task.getPipelineId());
        actionDTO.setActionType(actionType.label());
        JSONObject data = new JSONObject();
        data.put("ctx1", ctx1);
        data.put("ctx2", ctx2);
        data.put("ctx3", ctx3);
        context.put("data", data);
        actionDTO.setContext(context.toJSONString());
        boolean flag = this.save(actionDTO);
//        ActionDeStack actionStack = actionStackWrapper
//            .getActionDeStackByProjectId(task.getProjectId());
        ActionDeStack actionStack = actionStackWrapper
            .getActionDeStackByPipelineId(task.getPipelineId());
        actionStack.addUndoStack(actionDTO);
        compressedStack(actionStack);
        clearRedoStack(actionStack);
        return flag;
    }

    /**
     *
     * @param projectId
     * @return
     */
    public boolean initStackForProjectId(Long projectId) {
        return actionStackWrapper.initStackForProjectId(projectId, this);
    }

    /**
     *
     * @param pipelineId
     * @return
     */
    public boolean initStackForPipelineId(Long pipelineId) {
        return actionStackWrapper.initStackForPipelineId(pipelineId, this);
    }

    public boolean updateHandler(ActionDTO action, boolean isUndo) {
        ActionVO actionVO = action.view();
        JSONObject context = actionVO.getContextObj();
        JSONObject data = context.getJSONObject("data");
        List<TaskDTO> oldDtoArray = data.getJSONArray("ctx1").toJavaList(TaskDTO.class);
        List<TaskDTO> newDtoArray = data.getJSONArray("ctx2").toJavaList(TaskDTO.class);
        List<TaskDTO> array = newDtoArray;
        JSONArray widgets = context.getJSONArray("widgets");
        JSONObject jsonActions = context.getJSONObject("actions");
        JSONObject deleteActions = context.getJSONObject("deleteActions");
        boolean flag = true;
        if (isUndo) {
            array = oldDtoArray;
            if (CollectionUtil.isNotEmpty(deleteActions)) {//connectLine的撤销场景
                deleteCleanActions(deleteActions);
                //删完历史记录后，删除可能有的widgets
                List<WidgetDTO> widgetDTOS = this.deleteWidgets(deleteActions);
                context.put("deleteWidgets", widgetDTOS);
                action.setContext(context.toJSONString());
            }
        } else {
            //deleteLine的重做场景
            if (CollectionUtil.isNotEmpty(jsonActions)) {
                deleteCleanActions(jsonActions);
            }
            if (CollectionUtil.isNotEmpty(widgets)) {
                List<WidgetDTO> widgetDTOS = widgets.toJavaList(WidgetDTO.class);
                widgetDTOS.forEach(widget -> widgetMapper.deleteById(widget.getId()));
            }
        }
        for (TaskDTO dto: array) {
            flag = taskMapper.update(dto);
            if (!flag) {
                break;
            }
        }
        if (isUndo) {
            //加回widgets
            if (CollectionUtil.isNotEmpty(widgets)) {
                List<WidgetDTO> widgetDTOS = widgets.toJavaList(WidgetDTO.class);
                widgetDTOS.forEach(widget -> widgetMapper.save(widget));
            }
            //加回清洗actions
            if (CollectionUtil.isNotEmpty(jsonActions)) {
                addCleanActions(jsonActions);
            }
        } else {//connectLine的重做
            JSONArray deleteWidgets = context.getJSONArray("deleteWidgets");
            if (CollectionUtil.isNotEmpty(deleteWidgets)) {
                List<WidgetDTO> widgetDTOS = deleteWidgets.toJavaList(WidgetDTO.class);
                widgetDTOS.forEach(widgetDTO -> widgetMapper.save(widgetDTO));
            }
            if (CollectionUtil.isNotEmpty(deleteActions)) {
                addCleanActions(deleteActions);
            }
        }
        return flag;
    }

    private List<WidgetDTO> deleteWidgets(JSONObject deleteActions) {
        Set<String> keys = deleteActions.keySet();
        List<WidgetDTO> list = Lists.newArrayList();
        for (String key : keys) {
            List<WidgetDTO> widgetDTOS = widgetMapper.queryByTaskIdAndType(Long.valueOf(key));
            if (CollectionUtil.isNotEmpty(widgetDTOS)) {
                List<Long> param = Lists.newArrayList();
                param.add(Long.valueOf(key));
                widgetMapper.deleteByTasks(param);
                list.addAll(widgetDTOS);
            }
        }
        return list;
    }

    public void deleteCleanActions(JSONObject jsonActions) {
        Set<String> keys = jsonActions.keySet();
        for (String key : keys) {
            Long taskId = Long.valueOf(key);
            List<TaskInstanceDTO> actions = taskInstanceMapper.queryByTaskIdAndOrder(taskId);
            this.clearActions(actions, taskId);
        }
    }

    public void clearActions(List<TaskInstanceDTO> actions, Long taskId) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("taskId", taskId);
        map.put("id", actions.get(0).getId());
        TaskInstanceDTO taskInstanceDTO = taskInstanceMapper.queryById(actions.get(0).getId());
        if (null != taskInstanceDTO) {
            taskInstanceMapper.deleteActions(map);
        }
    }

    public void addCleanActions(JSONObject jsonActions) {
        Set<String> keys = jsonActions.keySet();
        for (String key : keys) {
            List<TaskInstanceDTO> actions = jsonActions.getJSONArray(key)
                .toJavaList(TaskInstanceDTO.class);
            actions.forEach(action -> taskInstanceMapper.save(action));
        }
    }

    public void rebuildCleanActions(JSONObject jsonActions) {
        if (CollectionUtil.isEmpty(jsonActions)) {
            return;
        }
        Set<String> keys = jsonActions.keySet();
        JSONObject temp = new JSONObject();
        for (String key : keys) {
            List<TaskInstanceDTO> actions = jsonActions.getJSONArray(key)
                .toJavaList(TaskInstanceDTO.class);
            Long currentTaskId = Long.valueOf(key);
            String table = getParentOutTable(taskMapper.queryById(currentTaskId));
            tColumnService.rebuildActions(actions, currentTaskId, table);
            temp.put(key, JSONArray.toJSON(actions));
        }
        jsonActions.clear();
        jsonActions.putAll(temp);
    }

    private String getParentOutTable(TaskDTO currentTask) {
        if (StringUtils.isEmpty(currentTask.getParentId())) {
            throw new DataScienceException("没有连接父节点，无清洗数据来源");
        }
        TaskDTO parentTask = taskMapper.queryById(Long.valueOf(currentTask.getParentId()));

        if (parentTask.getType() == TaskTypeEnum.TASK_TYPE_DATA.getVal()) {
            // 数据节点
            JSONObject data = parentTask.view().getData();
            JSONArray output = data.getJSONArray("output");
            JSONObject item = output.getJSONObject(0);
            return item.getString("tableName");
        }
        TaskInstanceDTO parentIns = taskInstanceMapper
                .queryLatestInstanceForTask(Long.valueOf(currentTask.getParentId()));
        if (parentIns == null) {
            return StringUtils.EMPTY;
        }
        JSONArray parentOutPut = PipelineUtil.extractOutPut(parentTask, parentIns);
        String table = "";
        for (int i = 0; i < parentOutPut.size(); i++) {
            if (!parentOutPut.getJSONObject(i).getString("tableName").contains("model")) {
                table = parentOutPut.getJSONObject(i).getString("tableName");
            }
        }
        return table;
    }

    public boolean addAndUpdateHandler(ActionDTO action, boolean isUndo) {
        ActionVO actionVO = action.view();
        JSONObject context = actionVO.getContextObj();
        JSONObject data = context.getJSONObject("data");
        List<TaskDTO> oldDtoArray = data.getJSONArray("ctx1").toJavaList(TaskDTO.class);
        List<TaskDTO> newDtoArray = data.getJSONArray("ctx2").toJavaList(TaskDTO.class);
        List<TaskDTO> ctx3Tasks = data.getJSONArray("ctx3").toJavaList(TaskDTO.class);
        JSONArray widgets = (JSONArray)context.remove("widgets");
        JSONObject jsonActions = (JSONObject)context.remove("actions");
        JSONObject deleteActions = context.getJSONObject("deleteActions");
        context.remove("tables");
        context.remove("views");
        //添加节点
        if (isUndo) {
            batchDeleteNode(context, ctx3Tasks);
        } else {
            // 逆向操作添加
            if (!taskService.batchAdd(ctx3Tasks)) {
                logger.error("batchAdd fail!!!");
                return false;
            }
        }
        //更新节点
        if (isUndo) {
            newDtoArray = oldDtoArray;
        }
        for (TaskDTO dto: newDtoArray) {
            taskMapper.update(dto);
        }
        //如果有，处理清洗的widget、历史记录
        if (isUndo) {
            //重新生成action
            batchAddContext(widgets, null);
            rebuildCleanActions(jsonActions);
            context.put("deleteActions", jsonActions);
        } else {
            if (CollectionUtil.isNotEmpty(deleteActions)) {
                saveWidgets(deleteActions, context);
                deleteCleanActions(deleteActions);
                context.put("actions", deleteActions);
            }
            batchAddContext(widgets, null);
            rebuildCleanActions(jsonActions);
        }
        action.setContext(context.toJSONString());
        return true;
    }

    private void batchDeleteNode(JSONObject context, List<TaskDTO> ctx3Tasks) {
        List<Long> ids = new ArrayList<>();
        Long pipelineId = ctx3Tasks.get(0).getPipelineId();
        for (TaskDTO task: ctx3Tasks) {
            ids.add(task.getId());
        }
        List<TaskDTO> deleteTasks = new ArrayList<>();
        taskService.batchDelete(context, ids, deleteTasks, pipelineId);
    }

    private void saveWidgets(JSONObject jsonActions, JSONObject context) {
        Set<String> keys = jsonActions.keySet();
        for (String key : keys) {
            Long taskId = Long.valueOf(key);
            taskService.deleteLineInitContext(context, taskId);
        }
    }

    public boolean addHandler(ActionDTO action, boolean isUndo) {
        return this.addHandler(action, isUndo, "ctx1");
    }

    public boolean addHandler(ActionDTO action, boolean isUndo, String ctxKey) {
        ActionVO actionVO = action.view();
        JSONObject context = actionVO.getContextObj();
        JSONObject data = context.getJSONObject("data");
        List<TaskDTO> tasks = data.getJSONArray(ctxKey).toJavaList(TaskDTO.class);
        if (isUndo) {
            // 逆向操作删除
            batchDeleteNode(context, tasks);
        } else {
            // 逆向操作添加
            if (!taskService.batchAdd(tasks)) {
                logger.error("batchAdd fail!!!");
                return false;
            }
            batchAddContext(context);
        }
        action.setContext(context.toJSONString());
        return true;
    }

    public boolean deleteHandler(ActionDTO action, boolean isUndo) {
        ActionVO actionVO = action.view();
        JSONObject context = actionVO.getContextObj();
        JSONObject data = context.getJSONObject("data");
        List<TaskDTO> tasks = data.getJSONArray("ctx1").toJavaList(TaskDTO.class);
        if (isUndo) {
            // 逆向操作，添加
            if (!taskService.batchAdd(tasks)) {
                logger.error("batchAdd fail!!!");
                return false;
            }
            batchAddContext(context);
        } else {
            // 逆向操作删除
            batchDeleteNode(context, tasks);
        }
        action.setContext(context.toJSONString());
        return true;
    }

    /**
     * 将widget,清洗记录等加回来
     * @param context
     */
    public void batchAddContext(JSONObject context) {
        JSONArray widgets = (JSONArray)context.remove("widgets");
        JSONObject jsonActions = (JSONObject)context.remove("actions");
        context.remove("tables");
        context.remove("views");
        batchAddContext(widgets, jsonActions);
    }

    public void batchAddContext(JSONArray widgets, JSONObject jsonActions) {
        //加回widgets
        if (CollectionUtil.isNotEmpty(widgets)) {
            List<WidgetDTO> widgetDTOS = widgets.toJavaList(WidgetDTO.class);
            widgetDTOS.forEach(widget -> widgetMapper.save(widget));
        }
        //加回清洗actions
        if (CollectionUtil.isNotEmpty(jsonActions)) {
            addCleanActions(jsonActions);
        }
    }

    /**
     * redo和undo 实际操作入口，根据不同的actionType执行不通的恢复处理逻辑
     * @param action
     * @return
     */
    public boolean recoverHandler(ActionDTO action, boolean isUndo) {
        if (action == null) {
            return false;
        }
        String actionType = action.getActionType();
        boolean flag = false;
        if (actionType.equals(ActionEnum.UPDATE.label())) {
            // 更新场景
            flag = this.updateHandler(action, isUndo);
        } else if (actionType.equals(ActionEnum.ADD.label())) {
            // 添加场景, 回退需要删除操作
            flag = this.addHandler(action, isUndo);
        } else if (actionType.equals(ActionEnum.DELETE.label())) {
            // 删除场景，回退需要添加操作
            flag = this.deleteHandler(action, isUndo);
        } else if (actionType.equals(ActionEnum.ADD_UPDATE.label())) {
            flag = this.addAndUpdateHandler(action, isUndo);
        } else if (actionType.equals(ActionEnum.CLEAN_ADD.label())) {
            //添加清洗记录，撤销需要删除记录
            flag = cleanAddHandler(action, isUndo);
        } else if (actionType.equals(ActionEnum.CLEAN_DELETE.label())) {
            //删除清洗记录，撤销需要添加记录
            flag = cleanAddHandler(action, !isUndo);
        } else if (actionType.equals(ActionEnum.CLEAN_UPDATE.label())) {
            flag = cleanUpdateHandler(action, isUndo);
        }
        if (flag ) {
            if (isUndo) {
                // if undo, then delete action from action table
                if (this.queryById(action.getId()) != null) {
                    try {
                        this.delete(action.getId());
                    } catch (Exception e) {
                        logger.error(e.getMessage());
                        return false;
                    }
                }
            } else {
                //重做，则将action加回到撤销表中
                save(action);
            }
        }
        return flag;
    }

    /**
     * 处理修改清洗的撤销
     * @param action 修改的记录
     * @param isUndo
     * @return
     */
    private boolean cleanUpdateHandler(ActionDTO action, boolean isUndo) {
        ActionVO actionVO = action.view();
        JSONObject context = actionVO.getContextObj();
        JSONObject data = context.getJSONObject("data");
        JSONObject item;
        if (isUndo) {//撤销，恢复成ctx1
            JSONArray ctx1 = data.getJSONArray("ctx1");
            item = ctx1.getJSONObject(0);
        } else {//重做，恢复成ctx2
            JSONArray ctx2 = data.getJSONArray("ctx2");
            item = ctx2.getJSONObject(0);
        }
        Integer index = item.getInteger("index");
        TaskInstanceDTO cleanAction = item.toJavaObject(TaskInstanceDTO.class);
        List<TaskInstanceDTO> actions = taskInstanceMapper.queryByTaskIdAndOrder(cleanAction.getTaskId());
        tColumnService.clearActions(actions, cleanAction.getTaskId());
        actions.remove(index.intValue());
        actions.add(index, cleanAction);
        TaskDTO currentTask = taskMapper.queryById(cleanAction.getTaskId());
        String table = getParentOutTable(currentTask);

        tColumnService.rebuildActions(actions, cleanAction.getTaskId(), table);
        return true;
    }

    /**
     * 处理添加清洗操作的撤销
     * @param action 添加的记录
     * @param isUndo
     * @return
     */
    public boolean cleanAddHandler(ActionDTO action, boolean isUndo) {
        ActionVO actionVO = action.view();
        JSONObject context = actionVO.getContextObj();
        JSONObject data = context.getJSONObject("data");
        JSONArray ctx1 = data.getJSONArray("ctx1");
        JSONObject item = ctx1.getJSONObject(0);
        Integer index = item.getInteger("index");
        TaskInstanceDTO cleanAction = item.toJavaObject(TaskInstanceDTO.class);
        List<TaskInstanceDTO> actions = taskInstanceMapper.queryByTaskIdAndOrder(cleanAction.getTaskId());
        tColumnService.clearActions(actions, cleanAction.getTaskId());
        TaskDTO currentTask = taskMapper.queryById(cleanAction.getTaskId());
        if (currentTask==null) {
            return false;
        }
        String table = getParentOutTable(currentTask);
        if (isUndo) {//撤销,删除清洗记录
            TaskInstanceDTO remove = actions.remove(index.intValue());
            //将该删除的操作的widget保存,有多个
            List<WidgetDTO> taskWidgets = widgetMapper.queryByTaskIdAndType(cleanAction.getTaskId());
            List<WidgetDTO> bindWidgets = PipelineUtil.extractBindWidgets(taskWidgets, remove);
            if (CollectionUtil.isNotEmpty(bindWidgets)) {
                context.put("widgets", bindWidgets);
                action.setContext(context.toJSONString());
            }
        } else {//重做，添加清洗记录
            actions.add(index, cleanAction);
            //将撤销时删除的widgets加回来
            JSONArray widgets = context.getJSONArray("widgets");
            if (CollectionUtil.isNotEmpty(widgets)) {
                for (int i = 0; i < widgets.size(); i++) {
                    widgetMapper.save(widgets.getObject(i, WidgetDTO.class));
                }
            }
        }
        //重新生成action
        tColumnService.rebuildActions(actions, cleanAction.getTaskId(), table);
        return true;
    }


    /**
     * undo 操作
     * @param pipelineId
     * @return
     */
    public boolean undo(Long pipelineId) {
        this.initStackForPipelineId(pipelineId);
        ActionDeStack actionDeStack = actionStackWrapper.getActionDeStackByPipelineId(pipelineId);
        ActionDTO undoAction = actionDeStack.undo();
        if (undoAction == null) {
            logger.error("undo empty!!!");
            return false;
        }
        boolean flag = this.recoverHandler(undoAction, true);
        if (!flag) {
            logger.error("recover fail!!!");
            actionDeStack.redo();
        }
        return flag;
    }

    /**
     * redo function
     * @param pipelineId
     * @return
     */
    public boolean redo(Long pipelineId) {
//        this.initStackForProjectId(projectId);
//        ActionDeStack actionDeStack = actionStackWrapper.getActionDeStackByProjectId(projectId);
        this.initStackForPipelineId(pipelineId);
        ActionDeStack actionDeStack = actionStackWrapper.getActionDeStackByPipelineId(pipelineId);
        ActionDTO redoAction = actionDeStack.redo();
        if (redoAction == null) {
            logger.error("redo empty!!!");
            return false;
        }
        boolean flag = this.recoverHandler(redoAction, false);
        if (!flag) {
            logger.error("recover fail!!!");
            actionDeStack.undo();
        }
        return flag;
    }

    /**
     * 清洗操作添加到撤销栈
     * @param actionType 操作的类型
     * @param ctx1 旧现场
     * @param ctx2 新现场
     */
    public boolean addCleanUpUndo(ActionEnum actionType, List<JSONObject> ctx1,
        List<JSONObject> ctx2, Long pipelineId) {
        TaskInstanceDTO instance = ctx1.get(0).toJavaObject(TaskInstanceDTO.class);
        //this.initStackForProjectId(instance.getProjectId());
        if (instance.getTaskId().equals(pipelineId)) {
            TaskDTO task = taskMapper.queryById(instance.getTaskId());
            if (task!=null&&task.getPipelineId()!=null) {
                pipelineId = task.getPipelineId();
            }
        }
        this.initStackForPipelineId(pipelineId);
        ActionDTO actionDTO = new ActionDTO();
        actionDTO.setUserId(JwtUtil.getCurrentUserId());
        actionDTO.setProjectId(instance.getProjectId());
        actionDTO.setPipelineId(pipelineId);
        actionDTO.setActionType(actionType.label());
        JSONObject context = new JSONObject();
        JSONObject data = new JSONObject();
        data.put("ctx1", ctx1);
        if (actionType == ActionEnum.CLEAN_DELETE) {
            List<WidgetDTO> taskWidgets = widgetMapper.queryByTaskIdAndType(instance.getTaskId());
            List<WidgetDTO> bindWidgets = PipelineUtil.extractBindWidgets(taskWidgets, instance);
            if (CollectionUtil.isNotEmpty(bindWidgets)) {
                context.put("widgets", bindWidgets);
            }
        }
        data.put("ctx2", ctx2);
        context.put("data", data);
        actionDTO.setContext(context.toJSONString());
        boolean flag = this.save(actionDTO);
//        ActionDeStack actionStack = actionStackWrapper
//            .getActionDeStackByProjectId(instance.getProjectId());

        ActionDeStack actionStack = actionStackWrapper
            .getActionDeStackByPipelineId(pipelineId);
        if (null != actionStack){
            actionStack.addUndoStack(actionDTO);
            compressedStack(actionStack);
        }
        return flag;
    }

    /**
     * 栈中的条数超过限制，删除
     */
    public void compressedStack(ActionDeStack actionStack) {
        int out = actionStack.outLimit();
        if (out > 0) {
            for (int i = 0; i < out; i++) {
                ActionDTO actionDTO = actionStack.removeUndoStack();
                removeAction(actionDTO);
                this.delete(actionDTO.getId());
            }
        }
    }

    /**
     * 删除action记录中的表
     * @param actionDTO
     */
    public void removeAction(ActionDTO actionDTO) {
        JSONObject context = JSONObject.parseObject(actionDTO.getContext());
        JSONArray tables = context.getJSONArray("tables");
        JSONArray views = context.getJSONArray("views");
        if (CollectionUtil.isNotEmpty(tables)) {
            gpDataProvider.dropRedundantTables(Joiner.on(",").join(tables), false);
        }
        if (CollectionUtil.isNotEmpty(views)) {
            gpDataProvider.dropRedundantTables(Joiner.on(",").join(views), true);
        }
    }

    /**
     * 清空重做栈
     * @param actionStack
     */
    public void clearRedoStack(ActionDeStack actionStack) {
        while (actionStack.redoStackSize() > 0) {
            ActionDTO redoAction = actionStack.removeRedoStack();
            removeAction(redoAction);
        }
    }

    /**
     * 在系统停止前清空redo栈,并删除表
     */
    @PreDestroy
    public void destroyRedoStack() {
        logger.info("system stopping... clear redoStack");
        Map<Long, ActionDeStack> stackWrapper = actionStackWrapper.getStackWrapper();
        Set<Long> keys = stackWrapper.keySet();
        if (CollectionUtil.isEmpty(keys)) {
            return;
        }
        for (Long key : keys) {
            ActionDeStack remove = stackWrapper.remove(key);
            clearRedoStack(remove);
        }
    }
}
